Across continents, millions of people are forced to make an impossible choice-stay and risk their lives or flee into the unknown.
War, persecution, economic collapse, and climate disasters have fueled an unprecedented surge in global displacement.
The scale of displacement is staggering, yet behind every statistic lies a personal tragedy-a family torn apart, a home left in ruins, a future rewritten.
The crisis isn’t just about movement; it’s about survival.
Code
import pandas as pdimport plotly.express as pxfrom IPython.display import HTMLdf = pd.read_csv('unicef_Indicator_1_Cleaned_1.csv')mdf = pd.read_csv('meta data (cleaned 1).csv')df = df.rename(columns={'Country': 'country', 'Year': 'year'})df = pd.merge(df, mdf[['country','year','Population, total']], on=['country','year'], how='left')df['total_refugees'] = (df['obs_value'] /1000) * df['Population, total']grouped = df.groupby('year', as_index=False).agg(total_refugees=('total_refugees','sum'))# creating the chartfig = px.bar( grouped, x='year', y='total_refugees', labels={'year':'Year','total_refugees':'Total Refugee Count'}, color='total_refugees', color_continuous_scale=['#fee5d9','#fcae91','#fb6a4a','#de2d26','#a50f15'], title='Global Refugee Trends Over Time', hover_data={'total_refugees':':.0f'})# Styling the barsfig.update_traces( marker_line_color='black', marker_line_width=1)# Axes marks changing the stylefig.update_yaxes( title_text='Total Refugee Count', tickformat='.1s', dtick=1e7, range=[0,4e7] )# Colorbar style change and markers positioning changedfig.update_layout( plot_bgcolor='#f8ebd8', paper_bgcolor='#f8ebd8', font=dict(family='Arial', size=12, color='black'), title_font_size=20, title_x=0.5, margin=dict(l=60,r=60,t=80,b=60), coloraxis_colorbar=dict( title='Total Refugee Count', orientation='h', tickmode='array', tickvals=[0,1e7,2e7,3e7,4e7], ticktext=['0M','10M','20M','30M','40M'], thickness=20, outlinecolor='black', outlinewidth=2, ticks='outside', ticklen=5, tickcolor='black', bgcolor='#f8ebd8', x=0.5, xanchor='center', y=-0.3, yanchor='top' ))# Customizing the X-axis style fig.update_xaxes( title_text='Year', tickmode='linear', dtick=1, showgrid=False, zeroline=False)# Displaying the output of the codeHTML(fig.to_html())
Who Bears The Weight of Displacement?
This chart highlights the top 15 countries that have hosted the most refugees over the years. What stands out is the overwhelming contribution of nations like Pakistan, Turkey, and Iran, who have shouldered a significant portion of the global refugee population. These countries, often not the wealthiest, show a remarkable level of humanitarian commitment.
While the refugee crisis is global, its burden is not equally shared. Nations with the fewest resources often bear the heaviest responsibility, hosting millions despite economic hardship. Meanwhile, wealthier countries-equipped with the means to help-remain on the sidelines. The numbers reveal a stark reality: humanitarian duty is not dictated by wealth, but by proximity and policy. Some nations have seen their refugee populations swell to make up a significant percentage of their total inhabitants, reshaping demographics, economies, and social structures. Others, despite their stability, take in only a fraction of those in need. This is not just a test of borders-it is a test of global responsibility.
Code
import pandas as pdimport plotly.express as pxfrom IPython.display import HTML# Loading and preparing the datadf = pd.read_csv('unicef_Indicator_1_Cleaned_1.csv')mdf = pd.read_csv('meta data (cleaned 1).csv')# Merging the two datadf = df.rename(columns={'Country': 'country', 'Year': 'year'})df = pd.merge(df, mdf[['country', 'year', 'Population, total']], on=['country', 'year'], how='left')# Calculating the total refugees countdf['total_refugees'] = (df['obs_value'] /1000) * df['Population, total']# Aggregating the total refugee count by country and sorting by descendingtop_countries = df.groupby('country')['total_refugees'].sum().reset_index()top_countries = top_countries.sort_values(by='total_refugees', ascending=False).head(15)# Creating the bar chartfig2 = px.bar( top_countries, x='total_refugees', y='country', orientation='h', title='Who Opens Their Doors?', labels={'country': 'Country', 'total_refugees': 'Total Refugee Count'}, color='total_refugees', color_continuous_scale='OrRd', hover_data={'total_refugees': ':.0f'}, category_orders={"country": top_countries['country'].tolist()} )# Adding the borders and updating the layoutfig2.update_traces( marker_line_color='black', marker_line_width=1)fig2.update_layout( paper_bgcolor='#f8ebd8', plot_bgcolor='#f8ebd8', margin=dict(l=20, r=20, t=40, b=40), xaxis_title='Total Refugee Count', yaxis_title='Country', coloraxis_showscale=False, font=dict(color='black'), title=dict( text='Who Opens Their Doors?', x=0.5, # Center the title xanchor='center' ))HTML(fig2.to_html())
Nowhere to Call Home
For millions, displacement is not just a statistic-it’s a struggle for survival. Families are torn apart, children grow up in limbo, and entire communities are forced to rebuild from nothing. While policies and economics shape refugee movement, the real question is how the world chooses to respond. Will refugees be seen as a burden, or as individuals with the potential to rebuild and thrive? The answer will define the future of displacement.
Code
import pandas as pdimport plotly.express as pxfrom IPython.display import HTMLimport pycountrydf = pd.read_csv('unicef_Indicator_1_Cleaned_1.csv')mdf = pd.read_csv('meta data (cleaned 1).csv')df = df.rename(columns={'Country':'country','Year':'year'})df = pd.merge(df, mdf[['country','year','Population, total']], on=['country','year'], how='left')df['total_refugees'] = (df['obs_value']/1000) * df['Population, total']choropleth_data = df.groupby('country', as_index=False)['total_refugees'].sum()def get_iso3(name):try: return pycountry.countries.lookup(name).alpha_3except: returnNonechoropleth_data['iso_alpha'] = choropleth_data['country'].apply(get_iso3)choropleth_data.dropna(subset=['iso_alpha'], inplace=True)# Creating the mapfig3 = px.choropleth( choropleth_data, locations='iso_alpha', color='total_refugees', hover_name='country', hover_data={'total_refugees':':.0f','iso_alpha':False}, color_continuous_scale='Oranges', title='Mapping the Global Refugee Footprint', labels={'total_refugees':'Total Refugee Count'}, projection='mercator')# changing the layout to remove scroll, and fill the spacefig3.update_geos( fitbounds="locations", visible=False, showcountries=True, countrycolor="black", showland=True, landcolor="#f8ebd8", showocean=True, oceancolor="lightblue")fig3.update_layout( autosize=True, height=500, width=800, margin=dict(l=20, r=20, t=50, b=20), paper_bgcolor="#f8ebd8", plot_bgcolor="#f8ebd8", coloraxis_colorbar=dict( title="Total Refugees", tickformat=",.0s", thickness=15, outlinecolor="black", outlinewidth=1 ))html = fig3.to_html(full_html=False, config={'responsive':True})HTML(html)
Wealth, Will, and Welcome
The relationship between GDP and refugee intake exposes deep inequalities. While economic powerhouses have the capacity to accommodate, they often don’t. Instead, those on the frontlines-often struggling themselves-become the world’s largest refugee hosts. The question isn’t just about who can take them in, but who chooses to. A troubling trend emerges: as global GDP rises, so do restrictive asylum policies. Nations with the means to help build walls instead of bridges, pushing responsibility onto their less affluent neighbors. Meanwhile, displacement continues to grow, leaving millions trapped in limbo.
Code
from plotnine import ( ggplot, aes, geom_point, geom_smooth, scale_color_gradient, labs, theme_minimal, theme, element_rect, element_text)( ggplot(df_plot, aes(x="total_refugees", y="gdp_per_capita"))# 1) Adding the Big black circles for the border effect+ geom_point( size=4.5, color="black", alpha=1 )# 2) small colour circle to show the data+ geom_point( aes(color="total_refugees"), size=4.5, alpha=0.8 )# 3) Adding a Regression line in the chart+ geom_smooth( method="lm", se=False, color="#a50f15", linetype="--", size=1.2 )# 4) making the Reds gradient colour scale+ scale_color_gradient( low="#fee5d9", high="#a50f15", name="Total Refugees" )+ labs( title="Wealth and Welcome: Do They Correlate?", x="Total Refugee Count", y="GDP per Capita (constant 2015 US$)" )+ theme_minimal()+ theme( plot_background=element_rect(fill="#f8ebd8", color=None), panel_background=element_rect(fill="#f8ebd8", color=None), legend_background=element_rect(fill="#f8ebd8", color=None), legend_position="right", plot_title=element_text(size=16, weight="bold"), axis_title=element_text(size=12), legend_title=element_text(size=11), legend_text=element_text(size=9) ))